/* 树链剖分 思想
* 1.关键 树中任意一条路径->O(logn)段连续区间
    (1)将树转化为一段区间
    (2)将树上的任意一条路径转化为 O(logn) 段区间

* 2.转换方法
    重儿子: 节点个数最多的儿子，且每个有儿子的节点 有且仅有一个重儿子
    先深搜出重儿子，然后按 dfs 序优先遍历重儿子的原则给节点重新编号(保证重链上的所有编号是连续的)，进而求出一段连续区间

* 3.使用
    对子树进行修改和查询，由于 dfs 遍历方式的原因，子树中的编号都是连续的，相当于对一段区间进行修改和查询
    对路径进行修改和查询，类似于 LCA 的思想，每次提取最低的重链构成的区间，然后对这些区间进行修改和查询
*/

#define DEBUG
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N=1e5+10, M=N<<1; //树是双向的
using ll=long long;
#define l(u) (u<<1)
#define r(u) (u<<1|1)
#define L(u) tree[u<<1]
#define R(u) tree[u<<1|1]

inline int read()
{
	int x=0;char c=getchar();
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48,c=getchar();
	return x;
}
inline void write(int x)
{
    if(x<0) putchar('-'), x*=-1;
	if (x>=10) write(x/10);
	putchar(x%10+48);
}//快读快输

struct Node
{
    int l, r;
    int sum; //权值和
    int change; //修改懒标记 -1不修改 0修改为0 1修改为1
}tree[N<<2];
int n, m, ans;
int w[N], h[N], e[M], ne[M], idx;
int id[N], cnt; //dfs序 dfs序的计数器(节点编号)
int dep[N], sz[N], top[N], fa[N], son[N]; //节点深度 当前节点的字数大小 节点所在重链的顶端节点 

inline void printSeg()
{
    for(int i=1; tree[i].l!=0; i++)
                printf("test:[%d, %d, %lld %d]\n", tree[i].l, tree[i].r, tree[i].sum, tree[i].change);
}

inline void AddEdge(int a, int b)
{
    e[idx]=b, ne[idx]=h[a], h[a]=idx++;
}

void dfs1(int u, int depth) //求每个点的深度 父节点 子树大小 儿子节点
{
    dep[u]=depth, sz[u]=1;
    for(int i=h[u]; ~i; i=ne[i])
    {
        int v=e[i];
        dfs1(v, depth+1);
        sz[u]+=sz[v];
        if(sz[son[u]]<sz[v]) son[u]=v; //找到重儿子
    }
}

void dfs2(int u, int t) //求dfs序 当前节点 当前重链的顶部节点 
{
    id[u]=++cnt, top[u]=t;
    if(!son[u]) return; //没有重儿子->叶子节点
    dfs2(son[u], t); //按照重链深搜
    for(int i=h[u]; ~i; i=ne[i])
    {
        int v=e[i];
        if(v==son[u]) continue; //去重 在重链上
        dfs2(v, v);//非重链的深搜
    }
}

inline void pushup(int u) //更新当前节点的sum
{
    tree[u].sum=L(u).sum+R(u).sum;
}

void pushdown(int u)
{
    auto &U=tree[u], &L=L(u), &R=R(u);
    if(~U.change)
    {
        L.sum=U.change*(L.r-L.l+1), L.change=U.change;
        R.sum=U.change*(R.r-R.l+1), R.change=U.change;
        U.change=-1;
    }
}

void build(int u, int l, int r)
{
    tree[u]={l, r, 0, -1}; //初始默认不修改
    if(l==r) return;
    int mid=l+r>>1;
    build(l(u), l, mid), build(r(u), mid+1, r);
    // pushup(u);
}

void modify(int u, int l, int r, int k) //区间修改
{
    auto &U=tree[u];
    if(l<=U.l && U.r<=r)
    {
        U.change=k;
        U.sum=k*(U.r-U.l+1);
        return;
    }
    pushdown(u);
    int mid=U.l+U.r>>1;
    if(l<=mid) modify(l(u), l, r, k);
    if(mid<r)  modify(r(u), l, r, k);
    pushup(u);
}

void modifyPath(int u, int v, int k) //利用dfs序更新路径u->v上的值
{
    while(top[u]!=top[v]) //u需要向上走至u,v在同一条重链上
    {
        if(dep[top[u]]<dep[top[v]]) swap(u, v);
        modify(1, id[top[u]], id[u], k);
        u=fa[top[u]]; 
    }
    if(dep[u]<dep[v]) swap(u, v);
    modify(1, id[v], id[u], k);
}

void modifyTree(int u, int k) //利用dfn在线段树区间上更新节点u和其子树的节点值
{
    modify(1, id[u], id[u]+sz[u]-1, k);
}

void solve()
{
    memset(h, -1, sizeof h);

    n=read();
    for(int i=2; i<=n; i++) 
    {
        int pa=read(); pa++; //下标修改为从1开始
        AddEdge(pa, i);
        fa[i]=pa;
    }

    dfs1(1, 1);
    dfs2(1, 1);
    build(1, 1, n);

    m=read();
    while(m--)
    {      
        char op[10]; scanf("%s", op);
        int x=read(); x++;
        int backup=tree[1].sum;

        if(!strcmp(op, "install")) //安装x及x之上的内容
        {    
            modifyPath(1, x, 1);//将根节点到x的路径上所有点的权值变成1
            write(tree[1].sum-backup);    
        }
        else if(!strcmp(op, "uninstall"))
        {
            modifyTree(x, 0);//将x为根的子树重所有点的权值变成0
            write(backup-tree[1].sum); 
        }
        puts("");
    }
}

signed main()
{
    #ifdef DEBUG
        freopen("./in.txt","r",stdin);
        freopen("./out.txt","w",stdout);
    #endif
    int T=1;
    // T=read();
    while(T--)
        solve();

    return 0;
}
